package neo4jUtil

import (
	"context"
	"fmt"
	"time"

	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)

var (
	Driver neo4j.DriverWithContext
	ctx    = context.Background()
)

const (
	Neo4jURI      = "bolt://47.100.111.28:7687"
	Neo4jUsername = "neo4j"
	Neo4jPassword = "4861abc165"
)

func InitNeo4j() error {
	var err error
	Driver, err = neo4j.NewDriverWithContext(
		Neo4jURI,
		neo4j.BasicAuth(Neo4jUsername, Neo4jPassword, ""),
	)
	if err != nil {
		return fmt.Errorf("创建 Neo4j 驱动失败: %v", err)
	}

	err = Driver.VerifyConnectivity(ctx)
	if err != nil {
		return fmt.Errorf("连接 Neo4j 失败: %v", err)
	}

	fmt.Println("✅ Neo4j 连接成功！")
	return nil
}

func CloseNeo4j() {
	if Driver != nil {
		Driver.Close(ctx)
	}
}

func CreateUserNode(userId int, username string) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			"MERGE (u:User {user_id: $userId}) SET u.username = $username, u.updated_at = datetime()",
			map[string]interface{}{
				"userId":   userId,
				"username": username,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func CreateArticleNode(articleId int, title string, categoryId int, userId int) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			`MERGE (a:Article {article_id: $articleId}) 
			 SET a.title = $title, a.category_id = $categoryId, a.user_id = $userId, a.updated_at = datetime()`,
			map[string]interface{}{
				"articleId":  articleId,
				"title":      title,
				"categoryId": categoryId,
				"userId":     userId,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func CreateCategoryNode(categoryId int, categoryName string) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			"MERGE (c:Category {category_id: $categoryId}) SET c.name = $categoryName, c.updated_at = datetime()",
			map[string]interface{}{
				"categoryId":   categoryId,
				"categoryName": categoryName,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func CreateLikeRelationship(userId int, articleId int) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			`MATCH (u:User {user_id: $userId})
			 MATCH (a:Article {article_id: $articleId})
			 MERGE (u)-[r:LIKED]->(a)
			 SET r.timestamp = datetime()`,
			map[string]interface{}{
				"userId":    userId,
				"articleId": articleId,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func DeleteLikeRelationship(userId int, articleId int) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			`MATCH (u:User {user_id: $userId})-[r:LIKED]->(a:Article {article_id: $articleId})
			 DELETE r`,
			map[string]interface{}{
				"userId":    userId,
				"articleId": articleId,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func CreateArticleCategoryRelationship(articleId int, categoryId int) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx,
			`MATCH (a:Article {article_id: $articleId})
			 MATCH (c:Category {category_id: $categoryId})
			 MERGE (a)-[r:BELONGS_TO]->(c)`,
			map[string]interface{}{
				"articleId":  articleId,
				"categoryId": categoryId,
			},
		)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func GetRecommendArticlesByCollaborativeFiltering(userId int, limit int) ([]map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		cypher := `
			MATCH (u:User {user_id: $userId})-[:LIKED]->(a:Article)<-[:LIKED]-(other:User)
			MATCH (other)-[:LIKED]->(rec:Article)
			WHERE NOT (u)-[:LIKED]->(rec)
			WITH rec, COUNT(DISTINCT other) as score
			ORDER BY score DESC
			LIMIT $limit
			RETURN rec.article_id as articleId, rec.title as title, score
		`
		result, err := tx.Run(ctx, cypher, map[string]interface{}{
			"userId": userId,
			"limit":  limit,
		})
		if err != nil {
			return nil, err
		}

		var articles []map[string]interface{}
		for result.Next(ctx) {
			record := result.Record()
			articleId, _ := record.Get("articleId")
			title, _ := record.Get("title")
			score, _ := record.Get("score")

			articles = append(articles, map[string]interface{}{
				"articleId": articleId,
				"title":     title,
				"score":     score,
			})
		}

		return articles, result.Err()
	})

	if err != nil {
		return nil, err
	}

	return result.([]map[string]interface{}), nil
}

func GetRecommendArticlesByContent(userId int, limit int) ([]map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		cypher := `
			MATCH (u:User {user_id: $userId})-[:LIKED]->(a:Article)-[:BELONGS_TO]->(c:Category)
			MATCH (c)<-[:BELONGS_TO]-(rec:Article)
			WHERE NOT (u)-[:LIKED]->(rec) AND rec.article_id <> a.article_id
			WITH rec, COUNT(*) as relevance
			WITH rec, relevance, COUNT { (rec)<-[:LIKED]-() } as likes
			ORDER BY relevance DESC, likes DESC
			LIMIT $limit
			RETURN rec.article_id as articleId, rec.title as title, relevance, likes
		`
		result, err := tx.Run(ctx, cypher, map[string]interface{}{
			"userId": userId,
			"limit":  limit,
		})
		if err != nil {
			return nil, err
		}

		var articles []map[string]interface{}
		for result.Next(ctx) {
			record := result.Record()
			articleId, _ := record.Get("articleId")
			title, _ := record.Get("title")
			relevance, _ := record.Get("relevance")
			likes, _ := record.Get("likes")

			articles = append(articles, map[string]interface{}{
				"articleId": articleId,
				"title":     title,
				"relevance": relevance,
				"likes":     likes,
			})
		}

		return articles, result.Err()
	})

	if err != nil {
		return nil, err
	}

	return result.([]map[string]interface{}), nil
}

func GetHotArticlesByNeo4j(limit int) ([]map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		cypher := `
			MATCH (a:Article)
			WITH a, COUNT { (a)<-[:LIKED]-() } as likeCount
			ORDER BY likeCount DESC
			LIMIT $limit
			RETURN a.article_id as articleId, a.title as title, likeCount
		`
		result, err := tx.Run(ctx, cypher, map[string]interface{}{
			"limit": limit,
		})
		if err != nil {
			return nil, err
		}

		var articles []map[string]interface{}
		for result.Next(ctx) {
			record := result.Record()
			articleId, _ := record.Get("articleId")
			title, _ := record.Get("title")
			likeCount, _ := record.Get("likeCount")

			articles = append(articles, map[string]interface{}{
				"articleId": articleId,
				"title":     title,
				"likeCount": likeCount,
			})
		}

		return articles, result.Err()
	})

	if err != nil {
		return nil, err
	}

	return result.([]map[string]interface{}), nil
}

func GetUserLikedArticles(userId int) ([]int, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		cypher := `
			MATCH (u:User {user_id: $userId})-[:LIKED]->(a:Article)
			RETURN a.article_id as articleId
		`
		result, err := tx.Run(ctx, cypher, map[string]interface{}{
			"userId": userId,
		})
		if err != nil {
			return nil, err
		}

		var articleIds []int
		for result.Next(ctx) {
			record := result.Record()
			articleId, _ := record.Get("articleId")
			if id, ok := articleId.(int64); ok {
				articleIds = append(articleIds, int(id))
			}
		}

		return articleIds, result.Err()
	})

	if err != nil {
		return nil, err
	}

	return result.([]int), nil
}

// GetSimilarArticlesByArticleId 根据文章ID推荐相似文章
// 推荐策略：
// 1. 优先推荐同分类的文章
// 2. 按点赞数排序（热门优先）
// 3. 排除当前文章本身
func GetSimilarArticlesByArticleId(articleId int, limit int) ([]map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		cypher := `
			MATCH (a:Article {article_id: $articleId})-[:BELONGS_TO]->(c:Category)
			MATCH (c)<-[:BELONGS_TO]-(similar:Article)
			WHERE similar.article_id <> $articleId
			WITH similar, COUNT { (similar)<-[:LIKED]-() } as likeCount
			ORDER BY likeCount DESC
			LIMIT $limit
			RETURN similar.article_id as articleId, similar.title as title, likeCount
		`
		result, err := tx.Run(ctx, cypher, map[string]interface{}{
			"articleId": articleId,
			"limit":     limit,
		})
		if err != nil {
			return nil, err
		}

		var articles []map[string]interface{}
		for result.Next(ctx) {
			record := result.Record()
			articleId, _ := record.Get("articleId")
			title, _ := record.Get("title")
			likeCount, _ := record.Get("likeCount")

			articles = append(articles, map[string]interface{}{
				"articleId": articleId,
				"title":     title,
				"likeCount": likeCount,
			})
		}

		return articles, result.Err()
	})

	if err != nil {
		return nil, err
	}

	return result.([]map[string]interface{}), nil
}

func ExecuteCypher(cypher string, params map[string]interface{}) error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx, cypher, params)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func ClearAllData() error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx, "MATCH (n) DETACH DELETE n", nil)
		if err != nil {
			return nil, err
		}
		return result.Consume(ctx)
	})

	return err
}

func CreateIndexes() error {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	indexes := []string{
		"CREATE INDEX user_id_index IF NOT EXISTS FOR (u:User) ON (u.user_id)",
		"CREATE INDEX article_id_index IF NOT EXISTS FOR (a:Article) ON (a.article_id)",
		"CREATE INDEX category_id_index IF NOT EXISTS FOR (c:Category) ON (c.category_id)",
	}

	for _, indexQuery := range indexes {
		_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
			result, err := tx.Run(ctx, indexQuery, nil)
			if err != nil {
				return nil, err
			}
			return result.Consume(ctx)
		})
		if err != nil {
			return fmt.Errorf("创建索引失败: %v", err)
		}
		time.Sleep(100 * time.Millisecond)
	}

	fmt.Println("✅ Neo4j 索引创建成功！")
	return nil
}

// GetGraphOverview 获取图谱概览数据
func GetGraphOverview(limit int, nodeType string, depth int) (map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		// 构建节点查询条件
		nodeFilter := ""
		if nodeType != "" {
			nodeFilter = fmt.Sprintf(":%s", nodeType)
		}

		// 查询节点
		nodeQuery := fmt.Sprintf(`
			MATCH (n%s)
			RETURN n, labels(n) as nodeLabels
			LIMIT $limit
		`, nodeFilter)

		nodeResult, err := tx.Run(ctx, nodeQuery, map[string]interface{}{
			"limit": limit,
		})
		if err != nil {
			return nil, err
		}

		nodes := []map[string]interface{}{}
		nodeIds := []interface{}{}

		for nodeResult.Next(ctx) {
			record := nodeResult.Record()
			node, _ := record.Get("n")
			labels, _ := record.Get("nodeLabels")

			if nodeData, ok := node.(neo4j.Node); ok {
				nodeLabels := labels.([]interface{})
				labelStr := ""
				if len(nodeLabels) > 0 {
					labelStr = nodeLabels[0].(string)
				}

				nodeMap := map[string]interface{}{
					"id":         fmt.Sprintf("%s_%d", labelStr, nodeData.GetProperties()["user_id"]),
					"label":      labelStr,
					"properties": nodeData.GetProperties(),
				}

				// 根据label类型选择合适的ID
				switch labelStr {
				case "User":
					if uid, ok := nodeData.GetProperties()["user_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("user_%v", uid)
						nodeIds = append(nodeIds, uid)
					}
				case "Article":
					if aid, ok := nodeData.GetProperties()["article_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("article_%v", aid)
						nodeIds = append(nodeIds, aid)
					}
				case "Category":
					if cid, ok := nodeData.GetProperties()["category_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("category_%v", cid)
						nodeIds = append(nodeIds, cid)
					}
				case "Tag":
					if tid, ok := nodeData.GetProperties()["tag_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("tag_%v", tid)
						nodeIds = append(nodeIds, tid)
					}
				}

				nodes = append(nodes, nodeMap)
			}
		}

		// 查询这些节点之间的关系
		edgeQuery := fmt.Sprintf(`
			MATCH (n%s)-[r]->(m%s)
			RETURN r, labels(startNode(r)) as sourceLabel, labels(endNode(r)) as targetLabel,
			       startNode(r) as sourceNode, endNode(r) as targetNode
			LIMIT $edgeLimit
		`, nodeFilter, nodeFilter)

		edgeResult, err := tx.Run(ctx, edgeQuery, map[string]interface{}{
			"limit":     limit,
			"edgeLimit": limit * 3,
		})
		if err != nil {
			return nil, err
		}

		edges := []map[string]interface{}{}
		edgeId := 0

		for edgeResult.Next(ctx) {
			record := edgeResult.Record()
			rel, _ := record.Get("r")
			sourceLabels, _ := record.Get("sourceLabel")
			targetLabels, _ := record.Get("targetLabel")
			sourceNode, _ := record.Get("sourceNode")
			targetNode, _ := record.Get("targetNode")

			if relData, ok := rel.(neo4j.Relationship); ok {
				edgeId++

				sourceLabel := ""
				targetLabel := ""
				if sl, ok := sourceLabels.([]interface{}); ok && len(sl) > 0 {
					sourceLabel = sl[0].(string)
				}
				if tl, ok := targetLabels.([]interface{}); ok && len(tl) > 0 {
					targetLabel = tl[0].(string)
				}

				// 构建source和target的ID
				sourceId := ""
				targetId := ""

				if sn, ok := sourceNode.(neo4j.Node); ok {
					switch sourceLabel {
					case "User":
						if uid, ok := sn.GetProperties()["user_id"]; ok {
							sourceId = fmt.Sprintf("user_%v", uid)
						}
					case "Article":
						if aid, ok := sn.GetProperties()["article_id"]; ok {
							sourceId = fmt.Sprintf("article_%v", aid)
						}
					case "Category":
						if cid, ok := sn.GetProperties()["category_id"]; ok {
							sourceId = fmt.Sprintf("category_%v", cid)
						}
					}
				}

				if tn, ok := targetNode.(neo4j.Node); ok {
					switch targetLabel {
					case "User":
						if uid, ok := tn.GetProperties()["user_id"]; ok {
							targetId = fmt.Sprintf("user_%v", uid)
						}
					case "Article":
						if aid, ok := tn.GetProperties()["article_id"]; ok {
							targetId = fmt.Sprintf("article_%v", aid)
						}
					case "Category":
						if cid, ok := tn.GetProperties()["category_id"]; ok {
							targetId = fmt.Sprintf("category_%v", cid)
						}
					}
				}

				edgeMap := map[string]interface{}{
					"id":         fmt.Sprintf("%s_%d", relData.Type, edgeId),
					"source":     sourceId,
					"target":     targetId,
					"label":      relData.Type,
					"properties": relData.Props,
				}

				edges = append(edges, edgeMap)
			}
		}

		return map[string]interface{}{
			"nodes": nodes,
			"edges": edges,
		}, nil
	})

	if err != nil {
		return nil, err
	}

	graphData := result.(map[string]interface{})

	// 获取统计信息
	statsResult, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		statsQuery := `
			MATCH (n)
			WITH labels(n) as label, count(*) as count
			RETURN label[0] as nodeType, count
		`
		result, err := tx.Run(ctx, statsQuery, nil)
		if err != nil {
			return nil, err
		}

		nodeTypes := make(map[string]interface{})
		totalNodes := 0

		for result.Next(ctx) {
			record := result.Record()
			nodeType, _ := record.Get("nodeType")
			count, _ := record.Get("count")

			if nt, ok := nodeType.(string); ok {
				if c, ok := count.(int64); ok {
					nodeTypes[nt] = int(c)
					totalNodes += int(c)
				}
			}
		}

		// 查询边统计
		edgeStatsQuery := `
			MATCH ()-[r]->()
			RETURN type(r) as edgeType, count(*) as count
		`
		edgeResult, err := tx.Run(ctx, edgeStatsQuery, nil)
		if err != nil {
			return nil, err
		}

		edgeTypes := make(map[string]interface{})
		totalEdges := 0

		for edgeResult.Next(ctx) {
			record := edgeResult.Record()
			edgeType, _ := record.Get("edgeType")
			count, _ := record.Get("count")

			if et, ok := edgeType.(string); ok {
				if c, ok := count.(int64); ok {
					edgeTypes[et] = int(c)
					totalEdges += int(c)
				}
			}
		}

		return map[string]interface{}{
			"totalNodes": totalNodes,
			"totalEdges": totalEdges,
			"nodeTypes":  nodeTypes,
			"edgeTypes":  edgeTypes,
		}, nil
	})

	if err != nil {
		return nil, err
	}

	graphData["summary"] = statsResult

	return graphData, nil
}

// GetGraphNodes 获取节点列表（分页、过滤、搜索）
func GetGraphNodes(page, size int, nodeType, keyword, sortField, sortOrder string) (map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		// 构建查询条件
		labelFilter := ""
		if nodeType != "" {
			labelFilter = fmt.Sprintf(":%s", nodeType)
		}

		whereClause := ""
		if keyword != "" {
			switch nodeType {
			case "User":
				whereClause = "WHERE n.username CONTAINS $keyword"
			case "Article":
				whereClause = "WHERE n.title CONTAINS $keyword"
			case "Category":
				whereClause = "WHERE n.name CONTAINS $keyword"
			case "Tag":
				whereClause = "WHERE n.name CONTAINS $keyword"
			default:
				whereClause = "WHERE (n.username CONTAINS $keyword OR n.title CONTAINS $keyword OR n.name CONTAINS $keyword)"
			}
		}

		// 构建排序
		orderClause := ""
		if sortField != "" {
			order := "DESC"
			if sortOrder == "asc" {
				order = "ASC"
			}
			orderClause = fmt.Sprintf("ORDER BY n.%s %s", sortField, order)
		}

		// 计算总数
		countQuery := fmt.Sprintf(`
			MATCH (n%s)
			%s
			RETURN count(n) as total
		`, labelFilter, whereClause)

		countResult, err := tx.Run(ctx, countQuery, map[string]interface{}{
			"keyword": keyword,
		})
		if err != nil {
			return nil, err
		}

		var total int64
		if countResult.Next(ctx) {
			record := countResult.Record()
			totalValue, _ := record.Get("total")
			total = totalValue.(int64)
		}

		// 查询节点
		skip := (page - 1) * size
		nodeQuery := fmt.Sprintf(`
			MATCH (n%s)
			%s
			WITH n, labels(n) as nodeLabels
			%s
			SKIP $skip
			LIMIT $limit
			OPTIONAL MATCH (n)<-[r_in]-()
			WITH n, nodeLabels, count(r_in) as inDegree
			OPTIONAL MATCH (n)-[r_out]->()
			RETURN n, nodeLabels, inDegree, count(r_out) as outDegree
		`, labelFilter, whereClause, orderClause)

		nodeResult, err := tx.Run(ctx, nodeQuery, map[string]interface{}{
			"keyword": keyword,
			"skip":    skip,
			"limit":   size,
		})
		if err != nil {
			return nil, err
		}

		nodes := []map[string]interface{}{}

		for nodeResult.Next(ctx) {
			record := nodeResult.Record()
			node, _ := record.Get("n")
			labels, _ := record.Get("nodeLabels")
			inDegree, _ := record.Get("inDegree")
			outDegree, _ := record.Get("outDegree")

			if nodeData, ok := node.(neo4j.Node); ok {
				nodeLabels := labels.([]interface{})
				labelStr := ""
				if len(nodeLabels) > 0 {
					labelStr = nodeLabels[0].(string)
				}

				nodeMap := map[string]interface{}{
					"id":         fmt.Sprintf("%s_%d", labelStr, nodeData.GetProperties()["user_id"]),
					"label":      labelStr,
					"properties": nodeData.GetProperties(),
					"stats": map[string]interface{}{
						"inDegree":  inDegree,
						"outDegree": outDegree,
					},
				}

				// 根据label类型选择合适的ID
				switch labelStr {
				case "User":
					if uid, ok := nodeData.GetProperties()["user_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("user_%v", uid)
					}
				case "Article":
					if aid, ok := nodeData.GetProperties()["article_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("article_%v", aid)
					}
				case "Category":
					if cid, ok := nodeData.GetProperties()["category_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("category_%v", cid)
					}
				case "Tag":
					if tid, ok := nodeData.GetProperties()["tag_id"]; ok {
						nodeMap["id"] = fmt.Sprintf("tag_%v", tid)
					}
				}

				nodes = append(nodes, nodeMap)
			}
		}

		return map[string]interface{}{
			"nodes": nodes,
			"pagination": map[string]interface{}{
				"page":  page,
				"size":  size,
				"total": total,
			},
		}, nil
	})

	if err != nil {
		return nil, err
	}

	return result.(map[string]interface{}), nil
}

// ExecuteQuery 执行任意Cypher查询并返回结果
func ExecuteQuery(cypher string) ([]map[string]interface{}, error) {
	session := Driver.NewSession(ctx, neo4j.SessionConfig{DatabaseName: "neo4j"})
	defer session.Close(ctx)

	result, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
		result, err := tx.Run(ctx, cypher, nil)
		if err != nil {
			return nil, err
		}

		records := []map[string]interface{}{}
		for result.Next(ctx) {
			record := result.Record()
			recordMap := make(map[string]interface{})

			// 遍历记录中的所有键值对
			for _, key := range record.Keys {
				value, ok := record.Get(key)
				if !ok {
					continue
				}

				// 转换Neo4j类型为普通类型
				recordMap[key] = convertNeo4jValue(value)
			}

			records = append(records, recordMap)
		}

		if err := result.Err(); err != nil {
			return nil, err
		}

		return records, nil
	})

	if err != nil {
		return nil, err
	}

	return result.([]map[string]interface{}), nil
}

// convertNeo4jValue 将Neo4j的特殊类型转换为普通类型
func convertNeo4jValue(value interface{}) interface{} {
	switch v := value.(type) {
	case neo4j.Node:
		return map[string]interface{}{
			"id":         v.GetId(),
			"labels":     v.Labels,
			"properties": v.GetProperties(),
		}
	case neo4j.Relationship:
		return map[string]interface{}{
			"id":         v.GetId(),
			"type":       v.Type,
			"startId":    v.StartId,
			"endId":      v.EndId,
			"properties": v.Props,
		}
	case neo4j.Path:
		nodes := []interface{}{}
		for _, node := range v.Nodes {
			nodes = append(nodes, convertNeo4jValue(node))
		}
		relationships := []interface{}{}
		for _, rel := range v.Relationships {
			relationships = append(relationships, convertNeo4jValue(rel))
		}
		return map[string]interface{}{
			"nodes":         nodes,
			"relationships": relationships,
		}
	case []interface{}:
		result := make([]interface{}, len(v))
		for i, item := range v {
			result[i] = convertNeo4jValue(item)
		}
		return result
	default:
		return value
	}
}
